<?php
/**
 * Geneone: Content Management Framework
 * Taxonomy
 *
 * http://geneone.neondragon.net/
 *
 * @package Geneone
 * @author Khlo
 * @version 1.0
 * @copyright 2004-2006 Geneone Development Team
 */
 
class Gene_Object_Taxonomy_Entry {
	/**
	 * Object ID
	 *
	 * @var integer
	 */
	var $objectId;
	
	/**
	 * Taxonomy User ID
	 *
	 * @var mixed Integer for User ID, false otherwise
	 */
	var $userId = false;
	
	/**
	 * Taxonomy Set ID
	 *
	 * @var integer
	 */
	var $setId;
	
	/**
	 * Labels for object in taxonomy set
	 *
	 * @var array
	 */
	var $labels;
	
	/**
	 * Table Name
	 *
	 * @var string
	 */
	var $tableName;
	
	/**
	 * Class Constructor
	 *
	 * @var integer $objectId Object ID
	 * @var integer $setId Taxonomy Set ID
	 * @var integer $userId User ID if user taxonomy desired or "*" for all user taxonomies
	 */
	function Gene_Object_Taxonomy_Entry($objectId, $setId, $userId=false) {
		$this->objectId = $objectId;
		$this->setId = $setId;
		$this->tableName = Gene::tableName("object_taxonomy");
		if ($userId) {
			$this->tableName = Gene::tableName("object_user_taxonomy");
			if ($userId != "*") {
				$this->userId = $userId;
			}
		}
	}
	
	/**
	 * Returns all labels in object taxonomy in set.
	 *
	 * @return array Labels
	 */
	function getAll() {
		if ($this->labels === null) {
			$db =& Gene::getDatabase();
			
			if ($this->userId) {
				$q = $db->prepare("SELECT label FROM ".$this->tableName." WHERE user_id=? AND set_id=? AND object_id=?");
				$res = $q->execute(array($this->userId, $this->setId, $this->objectId));
			} else {
				$q = $db->prepare("SELECT label FROM ".$this->tableName." WHERE set_id=? AND object_id=?");
				$res = $q->execute(array($this->setId, $this->objectId));
			}
			
			$this->labels = $res->fetchCol();
			$res->free();
		}
		
		return $this->labels;
	}
	
	/**
	 * Adds a label or labels for the object.
	 *
	 * @var string/array $labels Labels
	 * @return bool
	 */
	function add($labels) {
		if ($this->tableName == Gene::tableName("object_user_taxonomy") && !$this->userId) {
			return false;
		}
		
		$db =& Gene::getDatabase();
		if (!is_array($labels)) {
			$labels = array($labels);
		}
		
		$thislabels = $this->getAll();
		
		$add = array();
		
		foreach ($labels as $i) {
			$i = preg_replace('/\s\s+/', ' ', preg_replace("/[^a-zA-Z0-9:\. ]/", "", trim($i)));
			
			if ($i && !in_array($i, $thislabels)) {
				if ($this->userId) {
					$db->extended->autoExecute(
						$this->tableName,
						array(
							"user_id" => $this->userId,
							"set_id" => $this->setId,
							"label" => $i,
							"object_id" => $this->objectId,
						),
						MDB2_AUTOQUERY_INSERT
					);
				} else {
					$db->extended->autoExecute(
						$this->tableName,
						array(
							"set_id" => $this->setId,
							"label" => $i,
							"object_id" => $this->objectId,
						),
						MDB2_AUTOQUERY_INSERT
					);
				}
				
				$this->labels[] = $i;
			}
		}
		
		return true;
	}
	
	/**
	 * Removes a label or labels for the object.
	 *
	 * @var string/array $labels Labels
	 * @return bool
	 */
	function remove($labels) {
		$db =& Gene::getDatabase();
		if (!is_array($labels)) {
			$labels = array($labels);
		}
		
		$thislabels = $this->getAll();
		
		$remove = array();
		
		foreach ($thislabels as $j => $k) {
			if (in_array($k, $labels)) {
				unset($this->labels[$j]);
			}
			
			$remove[] = "'".$db->escapeSimple($k)."'";
		}
		
		if ($this->userId) {
			$q = $db->prepare("DELETE FROM ".$this->tableName." WHERE user_id=? AND set_id=? AND object_id=? AND label IN (".implode(",", $remove).")");
			$res = $q->execute(array($this->userId, $this->setId, $this->objectId));
		} else {
			$q = $db->prepare("DELETE FROM ".$this->tableName." WHERE set_id=? AND object_id=? AND label IN (".implode(",", $remove).")");
			$res = $q->execute(array($this->setId, $this->objectId));
		}
		
		return true;
	}
	
	/**
	 * Removes all labels for the object.
	 *
	 * @return bool
	 */
	function removeAll() {
		$db =& Gene::getDatabase();

		if ($this->userId) {
			$q = $db->prepare("DELETE FROM ".$this->tableName." WHERE user_id=? AND set_id=? AND object_id=?");
			$res = $q->execute(array($this->userId, $this->setId, $this->objectId));
		} else {
			$q = $db->prepare("DELETE FROM ".$this->tableName." WHERE set_id=? AND object_id=?");
			$res = $q->execute(array($this->setId, $this->objectId));
		}
		
		$this->labels = array();
		return true;
	}
	
	/**
	 * Returns Gene_Object_Taxonomy_Set object for this
	 * taxonomy's set.
	 *
	 * @return object Returns Gene_Object_Taxonomy_Set
	 */
	function &getSet() {
		require_once ("Gene/Object/Taxonomy/Set.php");
		$set =& new Gene_Object_Taxonomy_Set($this->setId);
		return $set;
	}
	
	/**
	 * Find similar taxonomied objects in set.
	 *
	 * @return array Objects
	 */
	function findSimilar($num=5) {
		$db =& Gene::getDatabase();
		
		$thislabels = $this->getAll();
		$labels = array();
		foreach ($thislabels as $i) {
			$labels[] = $db->quote($i); 
		}
		
		if (!count($labels)) {
			return array();
		}
		
		$db->setLimit($num);
		
		$q = $db->prepare("SELECT o.*, COUNT(label) AS matches FROM ".$this->tableName." t LEFT JOIN ".Gene::tableName("objects")." o ON (t.object_id=o.object_id) WHERE t.set_id=? AND t.label IN (".implode(",", $labels).") AND t.object_id <> ? GROUP BY t.object_id ORDER BY matches DESC, t_create DESC");
		$res = $q->execute(array($this->setId, $this->objectId));
		return $res->fetchAll();
		
	}
}
 
?>